package com.jinke.api.modules.ums.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jinke.api.common.api.CommonPage;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.modules.app.enums.BalanceLogType;
import com.jinke.api.modules.app.enums.ChannelStatus;
import com.jinke.api.modules.app.enums.OrderStatus;
import com.jinke.api.modules.app.enums.Roles;
import com.jinke.api.modules.app.model.BalanceLog;
import com.jinke.api.modules.app.model.Order;
import com.jinke.api.modules.app.request.*;
import com.jinke.api.modules.app.response.BatchEstimateRateResponse;
import com.jinke.api.modules.app.response.GetOrdersResponse;
import com.jinke.api.modules.app.service.BalanceLogService;
import com.jinke.api.modules.app.service.OrderService;
import com.jinke.api.modules.app.service.UserRechargeService;
import com.jinke.api.modules.base.service.BaseShipService;
import com.jinke.api.modules.base.service.ShipFactory;
import com.jinke.api.modules.ums.dto.BilledDto;
import com.jinke.api.modules.ums.model.Channel;
import com.jinke.api.modules.ums.model.UmsAdmin;
import com.jinke.api.modules.ums.model.UmsAdminRoleRelation;
import com.jinke.api.modules.ums.model.UmsRole;
import com.jinke.api.modules.ums.request.DoubtfulOrderFlowPageRequest;
import com.jinke.api.modules.ums.request.UNRefundedOrderPageRequest;
import com.jinke.api.modules.ums.service.ChannelService;
import com.jinke.api.modules.ums.service.UmsAdminRoleRelationService;
import com.jinke.api.modules.ums.service.UmsAdminService;
import com.jinke.api.modules.ums.service.UmsRoleService;
import com.jinke.api.modules.ums.vo.ApiLogVO;
import com.jinke.api.modules.ums.vo.DoubtfulOrderFlowPageVO;
import com.jinke.api.modules.ums.vo.UNRefundedOrderPageVO;
import com.jinke.api.security.util.AdminUserUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 承运商平台 前端控制器
 * </p>
 *
 * @author macro
 * @since 2024-01-15
 */
@RestController
@Api(tags = "订单管理")
@Tag(name = "订单管理", description = "订单管理")
@RequestMapping("/admin/order")
@Slf4j
public class AdminOrderController {

    @Resource
    private OrderService orderService;
    @Resource
    private ChannelService channelService;
    @Resource
    private UserRechargeService userRechargeService;
    @Resource
    private ShipFactory shipFactory;
    @Resource
    private BalanceLogService balanceLogService;
    @Resource
    private UmsAdminService umsAdminService;
    @Resource
    private UmsAdminRoleRelationService adminRoleRelationService;
    @Resource
    private UmsRoleService umsRoleService;


    @ApiOperation("订单列表")
    @RequestMapping(value = "/orders", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<CommonPage<GetOrdersResponse>> orders(@Validated OrderExportsRequest request) {
        return CommonResult.success(orderService.getGetOrdersResponseCommonPage(request));
    }

    @ApiOperation("取消/作废")
    @RequestMapping(value = "/orders/cancel", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<GetOrdersResponse> cancel(@RequestBody @Validated OrderCancelRequest request) {

        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        List<String> orderIds = request.getOrderIds();
        wrapper.in(orderIds != null, Order::getId, orderIds);
        wrapper.orderByDesc(Order::getId);
        wrapper.and(wp -> {
            wp.eq(Order::getStatus, OrderStatus.DRAFT).or().eq(Order::getStatus, OrderStatus.RECENT).or().eq(Order::getStatus, OrderStatus.IN_TRANSIT);
        });
        List<Order> orders = orderService.list(wrapper);
        if (CollectionUtil.isEmpty(orders)) {
            return CommonResult.failed("订单状态有误");
        }
        Set<Integer> channelIdSet = orders.stream().map(Order::getChannelId).collect(Collectors.toSet());
        Map<Integer, Channel> channelMap = channelService.list(new LambdaQueryWrapper<Channel>()
                        .in(Channel::getId , channelIdSet))
                        .stream().collect(Collectors.toMap(Channel::getId, Function.identity()));
        for (Order order : orders) {
            String orderNo = order.getOrderNo();
            Integer status = order.getStatus();
            if (OrderStatus.DRAFT.getValue() == status) {
                //对草稿取消即为作废
                order.setStatus(OrderStatus.VOIDED.getValue());

            } else {
                BaseShipService baseShipService = shipFactory.getBaseShipService(channelMap.get(order.getChannelId()));
                CommonResult commonResult = baseShipService.cancelLabel(order.getObjectId(),orderNo);
                //取消成功后更新记录
                // change 只有财务人员可以像之前一样直接取消，不走审核 管理人员取消和普通人一样，先走接口取消三方，再订单变成审核中
                UmsAdmin userInfo = AdminUserUtil.getUserInfo();
                List<Integer> userRoleIds = adminRoleRelationService.list(Wrappers.<UmsAdminRoleRelation>lambdaQuery()
                        .eq(UmsAdminRoleRelation::getAdminId, userInfo.getId())
                        .select(UmsAdminRoleRelation::getRoleId)).stream().map(UmsAdminRoleRelation::getRoleId).collect(Collectors.toList());
                List<UmsRole> adminRoles = Lists.newArrayList();
                if (CollectionUtil.isNotEmpty(userRoleIds)) {
                    adminRoles = umsRoleService.list(Wrappers.<UmsRole>lambdaQuery()
                            .in(UmsRole::getId, userRoleIds).eq(UmsRole::getStatus, ChannelStatus.ON)
                            .select(UmsRole::getName, UmsRole::getId));
                }
                UmsRole umsRole = new UmsRole();
                if (!adminRoles.isEmpty()) {
                    umsRole = adminRoles.get(0);
                }
                if (Optional.ofNullable(umsRole.getId()).orElse(-1).equals(Roles.FINANCE.getValue())) {
                    // 财务
                    //取消成功后更新记录
                    if (commonResult.isSucess()||commonResult.getMessage().equals("订单已删除，无需再次删除")
                            ||commonResult.getMessage().equals("撤消成功!")|| commonResult.getMessage().equals("OS：订单不存在或未完成或无权限!")) {
                        BigDecimal rate = order.getRate();
                        BigDecimal earnest = order.getEarnest();
                        List<BalanceLog.Detail> details = new ArrayList<>();

                        if (order.getEarnestTime() == null) {
                            // 退还保证金
                            details.add(new BalanceLog.Detail("寄件", rate.toString()));
                            details.add(new BalanceLog.Detail("保证金", earnest.toString()));
                        } else {
                            // 找到保证金退还记录
                            details.add(new BalanceLog.Detail("寄件", rate.toString()));
                            details.add(new BalanceLog.Detail("保证金", BigDecimal.ZERO.toString()));
                        }
                        //如果此人不是admin也变成取消中等待审核
                        order.setStatus(OrderStatus.CANCEL.getValue());
                        //退钱
                        userRechargeService.incr(order.getUserId(), rate.add(earnest), BalanceLogType.REFUND, "退款", orderNo, details);
                    }else {
                        return CommonResult.failed("第三方取消不成功");
                    }
                    order.setAuditorBy(AdminUserUtil.getUserInfo().getUsername());
                    order.setAuditorTime(LocalDateTime.now());
                } else {
                    // 其他
                    // 状态变更为取消中
                    order.setStatus(OrderStatus.CANCEL_ING.getValue());
                }
            }
            order.setCancelTime(LocalDateTime.now());
            orderService.updateById(order);
        }
        return CommonResult.success();
    }

    /**
     * 快递运单审核
     * @param request
     * @return
     */
    @ApiOperation("订单取消审核")
    @RequestMapping(value = "/orders/cancelAudit", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<GetOrdersResponse> cancelAudit(@RequestBody @Validated OrderCancelAuditRequest request) {
        //根据是同意还是拒绝还执行
        return request.getAccess().equals(1) ? orderService.cancelAudit(request) : orderService.reject(request);
        /*LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        List<String> orderIds = request.getOrderIds();
        wrapper.in(orderIds != null, Order::getId, orderIds);
        wrapper.eq(Order::getStatus, OrderStatus.CANCEL_ING);
        wrapper.orderByDesc(Order::getId);
        List<Order> orders = orderService.list(wrapper);

        for (Order order : orders) {
            try {
                String orderNo = order.getOrderNo();
                order.setAuditInfo(request.getAuditInfo());
                if (request.getAccess() == 1) {
                    BigDecimal rate = order.getRate();
                    BigDecimal earnest = order.getEarnest();
                    List<BalanceLog.Detail> details = new ArrayList<>();

                    if (order.getEarnestTime() == null) {
                        // 退还保证金
                        details.add(new BalanceLog.Detail("寄件", rate.toString()));
                        details.add(new BalanceLog.Detail("保证金", earnest.toString()));
                    } else {
                        details.add(new BalanceLog.Detail("寄件", rate.toString()));
                        details.add(new BalanceLog.Detail("保证金", BigDecimal.ZERO.toString()));
                    }
                    userRechargeService.incr(order.getUserId(), rate.add(earnest), BalanceLogType.REFUND, "退款", orderNo, details);
                    order.setStatus(OrderStatus.CANCEL.getValue());
                } else {
                    order.setStatus(OrderStatus.CANCEL_REJECT.getValue());
                }
                order.setAuditorBy(AdminUserUtil.getUserInfo().getUsername());
                order.setAuditorTime(LocalDateTime.now());
                orderService.updateById(order);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return CommonResult.success();*/
    }

    @ApiOperation("批量下单-按组预估版本")
    @RequestMapping(value = "/label/batchCreateNew", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<String> batchCreateNew(@RequestBody @Validated List<BatchCreateLabelOrderRequest> request) {
        Integer userId = AdminUserUtil.getUserId();
        return orderService.batch(request,userId);
    }

    @ApiOperation("批量下单-老版本")
    @RequestMapping(value = "/label/batchCreate", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<String> batchCreate(@RequestBody @Validated BatchCreateLabelOrderRequest request) {
        Integer userId = AdminUserUtil.getUserId();
        request.setUserId(userId);
         return orderService.batchOld(request);
    }

    @ApiOperation("批量费率估算")
    @RequestMapping(value = "/batchEstimateRate", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<List<BatchEstimateRateResponse>> batchEstimateRate(@RequestBody BatchEstimateRateRequest request) {
        return orderService.batchEstimateRate(request);
//        return orderService.batchEstimateRateNew(request);
    }

    @ApiOperation("批量下载面单")
    @RequestMapping(value = "/label/down", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<String> downLabel(@Validated OrderCancelRequest request) {
        return orderService.downLabel(request);
    }

    @ApiOperation("批量下载订单")
    @RequestMapping(value = "/order/down", method = RequestMethod.GET)
    public CommonResult<String> download(@Validated OrderExportsRequest request) {
        return orderService.download(request);
    }

    @ApiOperation("批量下载面单")
    @RequestMapping(value = "/label/downZip", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<String> downLabel2(@Validated OrderExportsRequest request) {
        return orderService.downLabel2(request);
    }

    @ApiOperation("释放保证金")
    @RequestMapping(value = "/order/releaseEarnest", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<String> releaseEarnest(@Validated @RequestBody OrderReleaseEarnestRequest request) {
        //return orderService.releaseEarnest(request);
        return orderService.releaseDeposit(request);
    }


    @ApiOperation("复制为新订单")
    @RequestMapping(value = "/order/copy", method = RequestMethod.POST)
    public CommonResult<String> copy(@Validated @RequestBody OrderCopyRequest request) throws IOException {
        return orderService.copy(request);
    }

    @ApiOperation("订单详情")
    @RequestMapping(value = "/orders/detail", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<GetOrdersResponse> detail(@Validated OrderDetailRequest request) {
        return orderService.detail(request);
    }

    /**
     * 账单补扣
     */
   @PostMapping("/billed")
    public CommonResult orderBilled(@Validated @RequestBody List<BilledDto> dtos) {
        return orderService.orderBilled(dtos);
    }

    /**
     * 发送邮件
     */
    /*@PostMapping("/send/mail")
    public CommonResult sendMail(@Validated @RequestBody SendMail mail) {
        return umsAdminService.sendMail(mail);
    }*/


    @ApiOperation("订单根据物流号取消审核")
    @PostMapping("/orders/auditByTNO")
    public CommonResult<String> auditByTrackingNum(@RequestBody @Validated OrderAuditRequest request) {
        return orderService.auditByTrackingNum(request);
    }

    @ApiOperation("保证金未退订单分页")
    @GetMapping("/unRefundedOrder/page")
    public CommonResult<CommonPage<UNRefundedOrderPageVO>> pageUNRefundedOrder(@Validated UNRefundedOrderPageRequest request) {
        return orderService.pageUNRefundedOrder(request);
    }

    @ApiOperation("流水存疑订单分页")
    @GetMapping("/doubtfulOrderFlow/page")
    public CommonResult<CommonPage<DoubtfulOrderFlowPageVO>> pageDoubtfulOrderFlow(@Validated DoubtfulOrderFlowPageRequest request) {
        Page<Order> orderPage = Optional.ofNullable(orderService.page(
                new Page<>(request.getPageNum(), request.getPageSize()),
                Wrappers.<Order>lambdaQuery()
                        .like(StrUtil.isNotBlank(request.getOrderNo()), Order::getOrderNo, request.getOrderNo())
                        .in(Order::getStatus, OrderStatus.RECENT.getValue(), OrderStatus.IN_TRANSIT.getValue(), OrderStatus.DELIVERED)
                        .notExists("SELECT 1 FROM balance_log bl WHERE order_no = bl.order_no")
                        .select(Order::getId, Order::getOrderNo, Order::getStatus, Order::getPdfUrl,
                                Order::getCreateTime, Order::getCreatedAt)
                        .orderByDesc(Order::getCreatedAt))).orElse(new Page<Order>());
        return CommonResult.success(CommonPage.restPage(
                new Page<DoubtfulOrderFlowPageVO>()
                .setCurrent(orderPage.getCurrent())
                .setSize(orderPage.getSize())
                .setTotal(orderPage.getTotal())
                .setRecords(
                        Optional.ofNullable(orderPage.getRecords()).orElse(Lists.newArrayList()).stream().map(order -> {
                            DoubtfulOrderFlowPageVO doubtfulOrderFlowPageVO = new DoubtfulOrderFlowPageVO();
                            BeanUtils.copyProperties(order, doubtfulOrderFlowPageVO);
                            return doubtfulOrderFlowPageVO;
                        }).collect(Collectors.toList())
                )));
    }
}

